﻿using System.Linq;
using Castle.ActiveRecord.Linq;
using ClientOverflow.DataTransferObjects;

namespace ClientOverflow.CommunicationServices.Data
{
    /// <summary>
    /// DtosConverionExtensions is a class implementing extension methods for converting DTO types to
    /// DataObject types. All the methods are extension methods so the DTOs don't have to know the
    /// data objects into which they are converted.
    /// </summary>
    internal static class DtosConverionExtensions
    {
        internal static DataObjects.User ToDataObject(this User dtoUser)
        {
            return new DataObjects.User
                       {
                           Name = dtoUser.Name,
                           Email = dtoUser.Email,
                           Department = dtoUser.Department.ToDataObject(),
                           Password = dtoUser.Password
                       };
        }

        internal static DataObjects.Question ToDataObject(this Question dtoQuestion)
        {
            if(DataObjects.Question.Queryable.Any(dbQuestion => dbQuestion.ID == dtoQuestion.ID))
            {
                return DataObjects.Question.Queryable.First(dbQuestion => dbQuestion.ID == dtoQuestion.ID);
            }

            var tags = dtoQuestion.Tags.Where(tag => !string.IsNullOrWhiteSpace(tag.Name))
                .Select(dtoTag => dtoTag.ToDataObject()).ToList();
            tags.ForEach(tag => tag.Save());

            return new DataObjects.Question
                       {
                           Title = dtoQuestion.Title,
                           Content = dtoQuestion.Content,
                           CorrectAnswerID = dtoQuestion.CorrectAnswerID,
                           Tags = tags
                       };
        }

        private static DataObjects.Tag ToDataObject(this Tag dtoTag)
        {
            if (ActiveRecordLinqBase<DataObjects.Tag>.Queryable.Any(dbTag => dtoTag.Name == dbTag.Name))
            {
                return ActiveRecordLinqBase<DataObjects.Tag>.Queryable.First(dbTag => dtoTag.Name == dbTag.Name);
            }

            return new DataObjects.Tag { Name = dtoTag.Name };
        }

        private static DataObjects.Department ToDataObject(this Department dtoDepartment)
        {
            if (ActiveRecordLinqBase<DataObjects.Department>.Queryable
                .Any(dbDepartment => dtoDepartment.Name == dbDepartment.Name))
            {
                return ActiveRecordLinqBase<DataObjects.Department>.Queryable
                    .First(dbDepartment => dtoDepartment.Name == dbDepartment.Name);
            }

            return new DataObjects.Department() {Name = dtoDepartment.Name};
        }

        internal static DataObjects.Answer ToDataObject(this Answer answer)
        {
            if(DataObjects.Answer.Queryable.Any(dbAnswer => dbAnswer.ID == answer.ID))
            {
                return DataObjects.Answer.Queryable.First(dbAnswer => dbAnswer.ID == answer.ID);
            }

            return new DataObjects.Answer
                       {
                           ID = answer.ID,
                           Content = answer.Content
                       };
        }
    }
}